"""
@author: 江同学呀
@file: base_field.py
@date: 2023/8/22 19:45
@desc:
"""
from abc import ABC
from typing import Type, Any, Union, Dict, Optional, Generator, TYPE_CHECKING

from espc.orm.model.base.base import _Base, CLASS_STATUS, OBJECT_STATUS


class _BaseField(_Base, ABC):
    """
    字段基类

    Attributes:
        _type (Type): 值类型
        _status (int): 类状态
        _value (Any): 值
        _default (Any): 默认值
        _field_name (str): 字段名
    """
    _type: Type = str
    _status: int = CLASS_STATUS
    _field_type: str = "_base"

    def __init__(self, field_name: str = None, value: Any = None, default: Any = None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._value: Any = value
        self._default: Any = default
        self._field_name: Optional[str] = field_name
        self._field_name_path: str = ""
        return

    # def __str__(self):
    #     return str(self._value)

    def __get__(self, instance: _Base, owner) -> Union["_BaseField", Any]:
        if not instance:
            return self
        if self._status == OBJECT_STATUS and instance._init_finished:
            return self._value
        return self

    def __set__(self, instance, value: Any):
        self._value = value
        return

    @property
    def value(self) -> Any:
        return self._value

    @value.setter
    def value(self, value: Any):
        self._value: Any = value
        return

    @property
    def field_name(self) -> Any:
        return self._field_name

    def _build(self) -> Dict:
        raise NotImplementedError

    def _get_custom_attrs(self: Union["_Base", Type["_Base"]]) -> Generator[str, None, None]:
        return (attr for attr in dir(self) if not attr.startswith("_"))

    def _init_field_name(self, field_name: str) -> "_BaseField":
        """
        初始化字段名
        :param field_name:
        :return:
        """
        from espc.orm.model.mapping.field.field_attribute import FieldsAttribute

        self._field_name: str = field_name
        for attr_name in self._get_custom_attrs():
            attr = getattr(self, attr_name)
            if isinstance(attr, _BaseField):
                # 此处与FieldsAttribute中的含义不同，此处意为在查询时使用完整字段路径名字
                attr._field_name = attr_name
                attr._init_field_name_path(parent_field_name=field_name)
        return self

    def _init_field_name_path(self, parent_field_name: str = "") -> "_BaseField":
        """
        初始化字段名路径
        :param parent_field_name:
        :return:
        """
        self._field_name_path: str = f"{parent_field_name}.{self._field_name}" if parent_field_name else self._field_name
        return self

    def _init_field_name_and_field_name_path(self, field_name: str, parent_field_name: str = "") -> "_BaseField":
        """
        初始化字段名和字段名路径
        :param field_name:
        :param parent_field_name:
        :return:
        """
        self._init_field_name(field_name=field_name)
        self._init_field_name_path(parent_field_name=parent_field_name)
        return self


